//
//  Laboratory.h
//  GPUProcessingTesting
//
//  Created by kadlubek47 on 12.07.2013.
//  Copyright (c) 2013 kadlubek47. All rights reserved.
//

#ifndef __GPUProcessingTesting__Laboratory__
#define __GPUProcessingTesting__Laboratory__

#include <string>
#include "TrialsSet.h"
#include "StatisticsComputator.h"

class Laboratory {
public:
    
    // Constructing
    Laboratory(const std::string resultsPath): resultsPath_(resultsPath) {}
    //.

    // Experiments
    void multiChannelExperiment();
    void minimumBufferSizeExperiment();
    void latencyBandwidthExperiment(unsigned int sizeOfDataTransfered, unsigned int repetition = 10000);
    //.

    // Test functions
    TrialsSet    bufferForEachChannel_testFunction (const unsigned int numOfChannels, const unsigned int lengthOfBlock, const unsigned int numOfBlocks);
    TrialsSet oneBufferForAllChannels_testFunction (const unsigned int numOfChannels, const unsigned int lengthOfBlock, const unsigned int numOfBlocks);
    //.
    
private:
    const std::string resultsPath_;
};

//valdate, simple kernel
/*
 #pragma mark validate
 
 void validate() {
 
 SpeedTestProc openCLProc;
 
 {
 openCLProc.setBuffers(128);
 float* data = new float[128];
 
 openCLProc.transferDataToGPU();
 openCLProc.executeTheSimplestKernel();
 openCLProc.transferDataFromGPU(data);
 
 openCLProc.setDataValue(5);
 
 openCLProc.transferDataToGPU();
 
 openCLProc.setDataValue(7);
 
 openCLProc.transferDataToGPU();
 openCLProc.executeTheSimplestKernel();
 openCLProc.transferDataFromGPU(data);
 }
 
 {
 float* data = new float[1000];
 simplyKernelTest(1000);
 openCLProc.transferDataFromGPU(data);
 data[1] = 58;
 }
 
 }
 
 
 
 #pragma mark >>test<<
 
 void simplyKernelTest( unsigned int sizeOfDataTransfered, unsigned int repetition)
 {
 using namespace std;
 SpeedTestProc openCLProc;
 Timer timer;
 
 openCLProc.setBuffers(sizeOfDataTransfered);
 float* data = new float[sizeOfDataTransfered];
 
 Timer mainTimer;
 double theWholeTime = 0;
 double *times = new double [repetition];
 
 mainTimer.start();
 for(int i = 0; i < repetition; ++i) {
 timer.start();
 openCLProc.transferDataToGPU();
 openCLProc.executeTheSimplestKernel();
 openCLProc.transferDataFromGPU(data);
 openCLProc.executeCommands();
 timer.stop();
 times[i] = timer.getTime() * 1000; //ms
 theWholeTime += timer.getTime();
 }
 mainTimer.stop();
 
 for(int i = 0; i < sizeOfDataTransfered; ++i)
 if( data[i] != 1)
 cout << "ERROR!!!!!!!!!!!!!!!!!" << endl;
 
 double averageTime = mainTimer.getTime() / repetition;
 double maximumDSP = (double)sizeOfDataTransfered/(double)44100;
 
 cout << "***" << endl;
 cout << "Executing simply kernel." << endl;
 cout << "***" << endl;
 cout << "Data size: " << sizeOfDataTransfered << endl;
 cout << "Repetition: " << repetition << endl;
 cout << "Average time: \t\t\t\t\t\t"; printTime(averageTime); cout << endl;
 cout << "Maximum DSP (one channel, 44100Hz): "; printTime(maximumDSP); cout << endl;
 cout << "1/2 of maximum DSP (one channel, 44100Hz): "; printTime(maximumDSP/2); cout << endl;
 cout << "***" << endl;
 cout << "Main timer: "; printTime(mainTimer.getTime()); cout << endl;
 cout << "Sum of times: "; printTime(theWholeTime); cout << endl;
 cout << "Times results from each [ms]:" << endl;
 printArray(times, repetition);
 cout << "***" << endl;
 cout << endl << endl;
 
 delete [] data;
 delete [] times;
 }
 */

#endif /* defined(__GPUProcessingTesting__Laboratory__) */
